package com.campusbackend.controller;

import com.campusbackend.entity.Result;
import com.campusbackend.entity.Teachers;
import com.campusbackend.entity.Awards;
import com.campusbackend.entity.CompetitionExperiences;
import com.campusbackend.entity.ProjectExperiences;
import com.campusbackend.entity.vo.AwardCreateVO;
import com.campusbackend.entity.vo.AwardUpdateVO;
import com.campusbackend.entity.vo.CompetitionCreateVO;
import com.campusbackend.entity.vo.CompetitionUpdateVO;
import com.campusbackend.entity.vo.ProjectCreateVO;
import com.campusbackend.entity.vo.ProjectUpdateVO;
import com.campusbackend.entity.vo.TeacherBasicInfoUpdateVO;
import com.campusbackend.entity.vo.TeacherCompleteInfoVO;
import com.campusbackend.entity.vo.TeacherHomepageUpdateVO;
import com.campusbackend.entity.vo.TeacherLoginVO;
import com.campusbackend.entity.vo.TeacherRegisterVO;
import com.campusbackend.entity.vo.TeacherListVO;
import com.campusbackend.service.AwardsService;
import com.campusbackend.service.CompetitionExperiencesService;
import com.campusbackend.service.ProjectExperiencesService;
import com.campusbackend.service.TeachersService;
import com.campusbackend.utils.JwtUtil;
import com.campusbackend.utils.ResultUtil;
import com.campusbackend.utils.ThreadLocalUtil;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 教师用户表 前端控制器
 * </p>
 *
 * @author yezi
 * @since 2025-07-24
 */
@Slf4j
@RestController
@Validated
@RequestMapping("/teacher")
public class TeachersController {

    @Autowired
    private TeachersService teachersService;
    
    @Autowired
    private AwardsService awardsService;
    
    @Autowired
    private CompetitionExperiencesService competitionExperiencesService;
    
    @Autowired
    private ProjectExperiencesService projectExperiencesService;
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    /**
     * 教师登录
     * @param employeeId 工号
     * @param password 密码
     * @return 登录结果
     */
    @PostMapping("/login")
    public Result<TeacherLoginVO> login(@Pattern(regexp="^\\S{1,50}$") String employeeId,
                                        @Pattern(regexp="^\\S{1,255}$") String password) {
        log.info("教师登录请求 - employeeId: {}", employeeId);
        
        // 根据工号查找教师
        Teachers teacher = teachersService.findByEmployeeId(employeeId);
        
        // 判断账号是否存在
        if (teacher == null) {
            return ResultUtil.fail("该工号不存在！");
        }
        
        // 检查账号状态
        if (teacher.getStatus() == 0) {
            return ResultUtil.fail("账号已被禁用！");
        }
        
        // 验证密码
        if (!passwordEncoder.matches(password, teacher.getPassword())) {
            return ResultUtil.fail("密码错误！");
        }
        
        // 生成JWT token
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", teacher.getId());
        claims.put("employeeId", teacher.getEmployeeId());
        claims.put("username", teacher.getUsername());
        claims.put("userType", "teacher");
        
        String token = JwtUtil.genToken(claims, 1000L * 60 * 60); // 1小时过期
        
        // 存储到Redis
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        operations.set(token, token, 1, TimeUnit.HOURS);
        
        // 创建返回对象
        TeacherLoginVO loginVO = new TeacherLoginVO(token, 200, teacher.getAuditStatus());
        
        return ResultUtil.success(loginVO);
    }

    /**
     * 教师注册
     * @param registerVO 注册信息
     * @return 注册结果
     */
    @PostMapping("/register")
    public Result<String> register(@Valid @RequestBody TeacherRegisterVO registerVO) {
        log.info("教师注册请求 - employeeId: {}, realName: {}", 
                 registerVO.getEmployee_id(), registerVO.getReal_name());
        
        try {
            String result = teachersService.registerTeacher(registerVO);
            
            // 判断注册是否成功
            if ("注册成功，请等待管理员审核".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("教师注册异常", e);
            return ResultUtil.fail("注册过程中发生错误，请稍后重试");
        }
    }

    /**
     * 检查工号是否已存在
     * @param employeeId 工号
     * @return 检查结果
     */
    @GetMapping("/checkEmployeeId")
    public Result<Boolean> checkEmployeeId(@Pattern(regexp="^\\S{1,50}$") String employeeId) {
        log.info("检查工号是否存在 - employeeId: {}", employeeId);
        
        try {
            boolean exists = teachersService.isEmployeeIdExists(employeeId);
            return ResultUtil.success(exists);
        } catch (Exception e) {
            log.error("检查工号异常", e);
            return ResultUtil.fail("检查工号时发生错误");
        }
    }

    @GetMapping("/checkIdCard")
    public Result<Boolean> checkIdCard(@Pattern(regexp="^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$") String idCard) {
        log.info("检查身份证号是否存在 - idCard: {}", idCard);
        try {
            boolean exists = teachersService.isIdCardExists(idCard);
            return ResultUtil.success(exists);
        } catch (Exception e) {
            log.error("检查身份证号异常", e);
            return ResultUtil.fail("检查身份证号时发生错误");
        }
    }

    @GetMapping("/checkPhone")
    public Result<Boolean> checkPhone(@Pattern(regexp="^1[3-9]\\d{9}$") String phone) {
        log.info("检查手机号是否存在 - phone: {}", phone);
        try {
            boolean exists = teachersService.isPhoneExists(phone);
            return ResultUtil.success(exists);
        } catch (Exception e) {
            log.error("检查手机号异常", e);
            return ResultUtil.fail("检查手机号时发生错误");
        }
    }

    @GetMapping("/checkEmail")
    public Result<Boolean> checkEmail(@Email String email) {
        log.info("检查邮箱是否存在 - email: {}", email);
        try {
            boolean exists = teachersService.isEmailExists(email);
            return ResultUtil.success(exists);
        } catch (Exception e) {
            log.error("检查邮箱异常", e);
            return ResultUtil.fail("检查邮箱时发生错误");
        }
    }

    /**
     * 获取教师个人信息
     * @return 教师信息
     */
    @GetMapping("/getTeacherInfo")
    public Result<Teachers> getTeacherInfo() {
        Map<String, Object> map = ThreadLocalUtil.get();
        String employeeId = (String) map.get("employeeId");
        Teachers teacher = teachersService.findByEmployeeId(employeeId);
        if (teacher != null) {
            // 不返回密码
            teacher.setPassword(null);
            return ResultUtil.success(teacher);
        }
        return ResultUtil.fail("用户不存在");
    }

    /**
     * 获取教师完整信息（包含基础信息、获奖情况、参赛经历、项目经历）
     * @param employeeId 教师工号
     * @return 教师完整信息
     */
    @GetMapping("/getCompleteInfo")
    public Result<TeacherCompleteInfoVO> getTeacherCompleteInfo(@RequestParam String employeeId) {
        log.info("获取教师完整信息 - employeeId: {}", employeeId);
        
        try {
            // 创建完整信息VO对象
            TeacherCompleteInfoVO completeInfo = new TeacherCompleteInfoVO();
            
            // 1. 获取教师基础信息
            Teachers teacher = teachersService.findByEmployeeId(employeeId);
            if (teacher == null) {
                return ResultUtil.fail("该工号的教师不存在");
            }
            // 不返回密码
            teacher.setPassword(null);
            completeInfo.setBasicInfo(teacher);
            
            Long teacherId = teacher.getId();
            
            // 2. 获取获奖情况
            List<Awards> awards = awardsService.getTeacherAwards(teacherId);
            completeInfo.setAwards(awards != null ? awards : new ArrayList<>());
            completeInfo.setTotalAwards(awards != null ? awards.size() : 0);
            
            // 3. 获取参赛经历
            List<CompetitionExperiences> competitions = competitionExperiencesService.getTeacherCompetitions(teacherId);
            completeInfo.setCompetitions(competitions != null ? competitions : new ArrayList<>());
            completeInfo.setTotalCompetitions(competitions != null ? competitions.size() : 0);
            
            // 4. 获取项目经历
            List<ProjectExperiences> projects = projectExperiencesService.getTeacherProjects(teacherId);
            completeInfo.setProjects(projects != null ? projects : new ArrayList<>());
            completeInfo.setTotalProjects(projects != null ? projects.size() : 0);
            
            log.info("获取教师完整信息成功 - 教师: {} ({}), 获奖: {}, 参赛: {}, 项目: {}", 
                    teacher.getRealName(),
                    employeeId,
                    completeInfo.getTotalAwards(), 
                    completeInfo.getTotalCompetitions(), 
                    completeInfo.getTotalProjects());
            
            return ResultUtil.success(completeInfo);
            
        } catch (Exception e) {
            log.error("获取教师完整信息异常:", e);
            return ResultUtil.fail("获取完整信息时发生错误");
        }
    }

    /**
     * 更新教师基本信息
     * @param updateVO 基本信息更新对象
     * @return 更新结果
     */
    @PutMapping("/updateBasicInfo")
    public Result<String> updateBasicInfo(@Valid @RequestBody TeacherBasicInfoUpdateVO updateVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        String employeeId = (String) map.get("employeeId");
        
        log.info("更新教师基本信息 - employeeId: {}, phone: {}, email: {}", 
                 employeeId, updateVO.getPhone(), updateVO.getEmail());
        
        try {
            String result = teachersService.updateBasicInfo(
                employeeId, 
                updateVO.getPhone(), 
                updateVO.getEmail(), 
                updateVO.getProfessionalTitle(), 
                updateVO.getIdCard()
            );
            
            if ("基本信息更新成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("更新基本信息异常", e);
            return ResultUtil.fail("更新基本信息时发生错误，请稍后重试");
        }
    }

    /**
     * 更新教师个人主页
     * @param updateVO 个人主页更新对象
     * @return 更新结果
     */
    @PutMapping("/updatePersonalHomepage")
    public Result<String> updatePersonalHomepage(@Valid @RequestBody TeacherHomepageUpdateVO updateVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        String employeeId = (String) map.get("employeeId");
        
        log.info("更新教师个人主页 - employeeId: {}, homepage: {}", 
                 employeeId, updateVO.getPersonalHomepage());
        
        try {
            String result = teachersService.updatePersonalHomepage(
                employeeId, 
                updateVO.getPersonalHomepage()
            );
            
            if ("个人主页更新成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("更新个人主页异常", e);
            return ResultUtil.fail("更新个人主页时发生错误，请稍后重试");
        }
    }

    // ==================== 获奖情况管理接口 ====================

    /**
     * 获取教师的所有获奖情况
     * @return 获奖情况列表
     */
    @GetMapping("/awards")
    public Result<List<Awards>> getTeacherAwards() {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("获取教师获奖情况 - teacherId: {}", teacherId);
        
        try {
            List<Awards> awards = awardsService.getTeacherAwards(teacherId);
            return ResultUtil.success(awards);
        } catch (Exception e) {
            log.error("获取获奖情况异常", e);
            return ResultUtil.fail("获取获奖情况时发生错误");
        }
    }

    /**
     * 添加获奖情况
     * @param createVO 获奖情况创建对象
     * @return 添加结果
     */
    @PostMapping("/awards")
    public Result<String> addTeacherAward(@Valid @RequestBody AwardCreateVO createVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("添加教师获奖情况 - teacherId: {}, awardName: {}", 
                 teacherId, createVO.getAwardName());
        
        try {
            String result = awardsService.addTeacherAward(teacherId, createVO);
            
            if ("获奖情况添加成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("添加获奖情况异常", e);
            return ResultUtil.fail("添加获奖情况时发生错误，请稍后重试");
        }
    }

    /**
     * 更新获奖情况
     * @param awardId 获奖ID
     * @param updateVO 获奖情况更新对象
     * @return 更新结果
     */
    @PutMapping("/awards/{awardId}")
    public Result<String> updateTeacherAward(@PathVariable Long awardId, 
                                             @Valid @RequestBody AwardUpdateVO updateVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("更新教师获奖情况 - teacherId: {}, awardId: {}, awardName: {}", 
                 teacherId, awardId, updateVO.getAwardName());
        
        // 确保路径参数和请求体中的ID一致
        updateVO.setId(awardId);
        
        try {
            String result = awardsService.updateTeacherAward(teacherId, updateVO);
            
            if ("获奖情况更新成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("更新获奖情况异常", e);
            return ResultUtil.fail("更新获奖情况时发生错误，请稍后重试");
        }
    }

    /**
     * 删除获奖情况
     * @param awardId 获奖ID
     * @return 删除结果
     */
    @DeleteMapping("/awards/{awardId}")
    public Result<String> deleteTeacherAward(@PathVariable Long awardId) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("删除教师获奖情况 - teacherId: {}, awardId: {}", teacherId, awardId);
        
        try {
            String result = awardsService.deleteTeacherAward(teacherId, awardId);
            
            if ("获奖情况删除成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("删除获奖情况异常", e);
            return ResultUtil.fail("删除获奖情况时发生错误，请稍后重试");
        }
    }

    // ==================== 参赛经历管理接口 ====================

    /**
     * 获取教师的所有参赛经历
     * @return 参赛经历列表
     */
    @GetMapping("/competitions")
    public Result<List<CompetitionExperiences>> getTeacherCompetitions() {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("获取教师参赛经历 - teacherId: {}", teacherId);
        
        try {
            List<CompetitionExperiences> competitions = competitionExperiencesService.getTeacherCompetitions(teacherId);
            return ResultUtil.success(competitions);
        } catch (Exception e) {
            log.error("获取参赛经历异常", e);
            return ResultUtil.fail("获取参赛经历时发生错误");
        }
    }

    /**
     * 添加参赛经历
     * @param createVO 参赛经历创建对象
     * @return 添加结果
     */
    @PostMapping("/competitions")
    public Result<String> addTeacherCompetition(@Valid @RequestBody CompetitionCreateVO createVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("添加教师参赛经历 - teacherId: {}, competitionName: {}", 
                 teacherId, createVO.getCompetitionName());
        
        try {
            String result = competitionExperiencesService.addTeacherCompetition(teacherId, createVO);
            
            if ("参赛经历添加成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("添加参赛经历异常", e);
            return ResultUtil.fail("添加参赛经历时发生错误，请稍后重试");
        }
    }

    /**
     * 更新参赛经历
     * @param competitionId 参赛经历ID
     * @param updateVO 参赛经历更新对象
     * @return 更新结果
     */
    @PutMapping("/competitions/{competitionId}")
    public Result<String> updateTeacherCompetition(@PathVariable Long competitionId, 
                                                   @Valid @RequestBody CompetitionUpdateVO updateVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("更新教师参赛经历 - teacherId: {}, competitionId: {}, competitionName: {}", 
                 teacherId, competitionId, updateVO.getCompetitionName());
        
        // 确保路径参数和请求体中的ID一致
        updateVO.setId(competitionId);
        
        try {
            String result = competitionExperiencesService.updateTeacherCompetition(teacherId, updateVO);
            
            if ("参赛经历更新成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("更新参赛经历异常", e);
            return ResultUtil.fail("更新参赛经历时发生错误，请稍后重试");
        }
    }

    /**
     * 删除参赛经历
     * @param competitionId 参赛经历ID
     * @return 删除结果
     */
    @DeleteMapping("/competitions/{competitionId}")
    public Result<String> deleteTeacherCompetition(@PathVariable Long competitionId) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("删除教师参赛经历 - teacherId: {}, competitionId: {}", teacherId, competitionId);
        
        try {
            String result = competitionExperiencesService.deleteTeacherCompetition(teacherId, competitionId);
            
            if ("参赛经历删除成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("删除参赛经历异常", e);
            return ResultUtil.fail("删除参赛经历时发生错误，请稍后重试");
        }
    }

    // ==================== 项目经历管理接口 ====================

    /**
     * 获取教师的所有项目经历
     * @return 项目经历列表
     */
    @GetMapping("/projects")
    public Result<List<ProjectExperiences>> getTeacherProjects() {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("获取教师项目经历 - teacherId: {}", teacherId);
        
        try {
            List<ProjectExperiences> projects = projectExperiencesService.getTeacherProjects(teacherId);
            return ResultUtil.success(projects);
        } catch (Exception e) {
            log.error("获取项目经历异常", e);
            return ResultUtil.fail("获取项目经历时发生错误");
        }
    }

    /**
     * 添加项目经历
     * @param createVO 项目经历创建对象
     * @return 添加结果
     */
    @PostMapping("/projects")
    public Result<String> addTeacherProject(@Valid @RequestBody ProjectCreateVO createVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("添加教师项目经历 - teacherId: {}, projectName: {}", 
                 teacherId, createVO.getProjectName());
        
        try {
            String result = projectExperiencesService.addTeacherProject(teacherId, createVO);
            
            if ("项目经历添加成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("添加项目经历异常", e);
            return ResultUtil.fail("添加项目经历时发生错误，请稍后重试");
        }
    }

    /**
     * 更新项目经历
     * @param projectId 项目经历ID
     * @param updateVO 项目经历更新对象
     * @return 更新结果
     */
    @PutMapping("/projects/{projectId}")
    public Result<String> updateTeacherProject(@PathVariable Long projectId, 
                                               @Valid @RequestBody ProjectUpdateVO updateVO) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("更新教师项目经历 - teacherId: {}, projectId: {}, projectName: {}", 
                 teacherId, projectId, updateVO.getProjectName());
        
        // 确保路径参数和请求体中的ID一致
        updateVO.setId(projectId);
        
        try {
            String result = projectExperiencesService.updateTeacherProject(teacherId, updateVO);
            
            if ("项目经历更新成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("更新项目经历异常", e);
            return ResultUtil.fail("更新项目经历时发生错误，请稍后重试");
        }
    }

    /**
     * 删除项目经历
     * @param projectId 项目经历ID
     * @return 删除结果
     */
    @DeleteMapping("/projects/{projectId}")
    public Result<String> deleteTeacherProject(@PathVariable Long projectId) {
        Map<String, Object> map = ThreadLocalUtil.get();
        Long teacherId = ((Number) map.get("id")).longValue();
        
        log.info("删除教师项目经历 - teacherId: {}, projectId: {}", teacherId, projectId);
        
        try {
            String result = projectExperiencesService.deleteTeacherProject(teacherId, projectId);
            
            if ("项目经历删除成功".equals(result)) {
                return ResultUtil.success(result);
            } else {
                return ResultUtil.fail(result);
            }
        } catch (Exception e) {
            log.error("删除项目经历异常", e);
            return ResultUtil.fail("删除项目经历时发生错误，请稍后重试");
        }
    }

    /**
     * 获取所有教师列表
     * @return 教师列表
     */
    @GetMapping("/all")
    public Result<List<TeacherListVO>> getAllTeachers() {
        log.info("获取所有教师列表请求");
        
        try {
            List<TeacherListVO> teachers = teachersService.getAllTeachers();
            log.info("获取教师列表成功，共 {} 位教师", teachers.size());
            return ResultUtil.success(teachers);
        } catch (Exception e) {
            log.error("获取所有教师列表异常:", e);
            return ResultUtil.fail("获取教师列表失败");
        }
    }

    /**
     * 搜索教师
     * @param keyword 搜索关键词（工号或姓名）
     * @return 教师列表
     */
    @GetMapping("/search")
    public Result<List<TeacherListVO>> searchTeachers(@RequestParam(required = false) String keyword) {
        log.info("搜索教师请求 - keyword: {}", keyword);
        
        try {
            List<TeacherListVO> teachers = teachersService.searchTeachers(keyword);
            log.info("搜索教师成功，共找到 {} 位教师", teachers.size());
            return ResultUtil.success(teachers);
        } catch (Exception e) {
            log.error("搜索教师异常:", e);
            return ResultUtil.fail("搜索教师失败");
        }
    }

}
